﻿using ICSharpCode.SharpZipLib.Zip;
using System;
using System.IO;
using System.Linq;

namespace Leaf.NetCore.HotUpdate
{
    public class ZipHelper
    {
        /// <summary>
        /// 压缩文件
        /// </summary>
        /// <param name="source">要压缩目录</param>
        /// <param name="outpath">输出文件路径及名称.zip</param>
        /// <param name="cLevel">压缩等级</param>
        /// <param name="excludeExt">排查后缀</param>
        /// <param name="excludeDir">排除文件夹</param>
        /// <param name="excludeFile">排除文件</param>
        public bool CreatZipDir(string source, string outpath, string[] exclude = null)
        {
            if (Directory.Exists(source) == false)
            {
                return false;
            }
            if (Path.GetExtension(outpath) != ".zip")
            {
                return false;
            }
            if (exclude == null)
            {
                //System.IO.Compression.ZipFile.CreateFromDirectory(source, outpath, CompressionLevel.Fastest, false);
                FastZip fz = new FastZip();
                //fz.CreateEmptyDirectories = true;
                fz.CreateZip(outpath, source, true, "", "");
            }
            else
            {
                using (ICSharpCode.SharpZipLib.Zip.ZipFile zip = ICSharpCode.SharpZipLib.Zip.ZipFile.Create(outpath))
                {
                    zip.BeginUpdate();
                    zip.NameTransform = new ZipNameTransform(source);
                    ZipAddFile(source, zip, exclude);
                    zip.CommitUpdate();
                }
            }
            return true;
        }

        /// <summary>
        /// 添加压缩文件可排除目录、扩展名、文件
        /// </summary>
        /// <param name="source"></param>
        /// <param name="zipFile"></param>
        /// <param name="exclude"></param>
        /// <returns></returns>
        private static bool ZipAddFile(string source, ICSharpCode.SharpZipLib.Zip.ZipFile zipFile, string[] exclude = null)
        {
            bool ret = false;
            try
            {
                source = source.EndsWith(@"\") ? source : source + @"\";

                if (Directory.Exists(source))
                {
                    var getFiles = Directory.GetFiles(source);
                    string _fileName = "";
                    string _ext = "";
                    string _dir = "";
                    foreach (string fls in getFiles)
                    {
                        _fileName = fls.Split('\\')[fls.Split('\\').Length - 1];
                        _ext = "." + fls.Split('.')[fls.Split('.').Length - 1];
                        //FileInfo flinfo = new FileInfo(fls);
                        if (exclude.Contains(_fileName) || exclude.Contains(_ext))
                        {
                            continue;
                        }

                        zipFile.Add(fls);
                    }
                    foreach (string drs in Directory.GetDirectories(source))
                    {
                        _dir = drs.Split('\\')[drs.Split('\\').Length - 1];
                        if (exclude.Contains(_dir))
                        {
                            continue;
                        }
                        //zipFile.AddDirectory(drinfo.FullName);
                        if (ZipAddFile(drs, zipFile, exclude) == false)
                            ret = false;
                    }
                }
                ret = true;
            }
            catch (Exception ex)
            {
                ret = false;
            }
            return ret;
        }

        /// <summary>
        /// 解压缩一个 zip 文件。
        /// </summary>
        /// <param name="zipedFile">压缩文件</param>
        /// <param name="strDirectory">解压目录</param>
        ///  <param name="overWrite">是否覆盖已存在的文件。</param>
        /// <param name="password">zip 文件的密码。</param>
        public static void UnZip(string zipedFile, string strDirectory, bool overWrite = true, string password = "")
        {
            if (strDirectory == "")
                strDirectory = Directory.GetCurrentDirectory();
            if (!strDirectory.EndsWith("\\"))
                strDirectory = strDirectory + "\\";

            using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipedFile)))
            {
                if (string.IsNullOrWhiteSpace(password) == false)
                {
                    s.Password = password;
                }
                ZipEntry theEntry;

                while ((theEntry = s.GetNextEntry()) != null)
                {
                    string directoryName = "";
                    string pathToZip = "";
                    pathToZip = theEntry.Name;

                    if (pathToZip != "")
                        directoryName = Path.GetDirectoryName(pathToZip) + "\\";

                    string fileName = Path.GetFileName(pathToZip);

                    Directory.CreateDirectory(strDirectory + directoryName);

                    if (fileName != "")
                    {
                        if ((File.Exists(strDirectory + directoryName + fileName) && overWrite) || (!File.Exists(strDirectory + directoryName + fileName)))
                        {
                            using (FileStream streamWriter = File.Create(strDirectory + directoryName + fileName))
                            {
                                int size = 2048;
                                byte[] data = new byte[2048];
                                while (true)
                                {
                                    size = s.Read(data, 0, data.Length);

                                    if (size > 0)
                                        streamWriter.Write(data, 0, size);
                                    else
                                        break;
                                }
                                streamWriter.Close();
                            }
                        }
                    }
                }

                s.Close();
            }
        }
    }
}